package github.kawaiior.yuanchuxiuzhen.common.container;

import github.kawaiior.yuanchuxiuzhen.common.item.misc.ManaStoneItem;
import github.kawaiior.yuanchuxiuzhen.common.item.misc.SplinterItem;
import github.kawaiior.yuanchuxiuzhen.common.tileentity.MaterialConverterTileEntity;
import github.kawaiior.yuanchuxiuzhen.core.init.BlockInit;
import github.kawaiior.yuanchuxiuzhen.core.init.ContainerInit;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.ClickType;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IWorldPosCallable;
import net.minecraft.util.math.BlockPos;


import java.util.Objects;


public class MaterialConverterContainer extends Container {

    public final MaterialConverterTileEntity tileEntity;

    private final IWorldPosCallable ableToInteract;

    public MaterialConverterContainer(final int id, final PlayerInventory playerInventory, final MaterialConverterTileEntity entity) {
        super(ContainerInit.MATERIAL_CONVERTER_GUI_CONTAINER.get(),id);
        this.tileEntity = entity;
        this.ableToInteract = IWorldPosCallable.of(Objects.requireNonNull(tileEntity.getWorld()),tileEntity.getPos());

        for (int i = 0; i < entity.LENGTH; i++) {
            this.addSlot(new Slot(entity.getInventory(), i, i*18+9, 22));
        }

        for (int i = 0; i < entity.LENGTH; i++) {
            this.addSlot(new Slot(entity.getShopInventory(), i, i*18+9, 58));
        }

        // add player inventory
        for(int i =0;i<9;i++){
            this.addSlot(new Slot(playerInventory,i,i*18+9,152-9));
            this.addSlot(new Slot(playerInventory,i+9,i*18+9,94-9));
            this.addSlot(new Slot(playerInventory,i+18,i*18+9,112-9));
            this.addSlot(new Slot(playerInventory,i+27,i*18+9,130-9));
        }
    }

    public MaterialConverterContainer(final int id, final PlayerInventory playerInventory, final PacketBuffer data) {
        this(id, playerInventory, getTileEntity(playerInventory,data));
    }

    @Override
    public boolean canInteractWith(PlayerEntity playerIn) {
        return isWithinUsableDistance(ableToInteract,playerIn, BlockInit.MATERIAL_CONVERTER_BLOCK.get());
    }

    public static MaterialConverterTileEntity getTileEntity(PlayerInventory playerInventory, PacketBuffer data){
        Objects.requireNonNull(playerInventory,"玩家物品栏不能为空");
        Objects.requireNonNull(data,"数据包不能为空");

        BlockPos blockPos = data.readBlockPos();
        TileEntity tileEntity = playerInventory.player.world.getTileEntity(blockPos);

        if(tileEntity instanceof MaterialConverterTileEntity){
            return (MaterialConverterTileEntity) tileEntity;
        }
        throw new IllegalStateException("invalid tile entity");
    }

    @Override
    public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {

        if (clickTypeIn == ClickType.PICKUP){
            return pickup(slotId, dragType, clickTypeIn, player);
        }else if (clickTypeIn == ClickType.QUICK_MOVE){
            return quickMove(slotId, player);
        }else if (clickTypeIn == ClickType.PICKUP_ALL){
            return ItemStack.EMPTY;
        }else if (clickTypeIn == ClickType.QUICK_CRAFT){
            return player.inventory.getItemStack();
        }

        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

    // TODO: 写的有点看不懂了，有时间重构一下
    private ItemStack pickup(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player){
        if (slotId > 18){
            return super.slotClick(slotId, dragType, clickTypeIn, player);
        }

        ItemStack playerInvStack = player.inventory.getItemStack();

        if (!playerInvStack.isEmpty()){

            if (slotId < 0){
                player.dropItem(playerInvStack, true);
                player.inventory.setItemStack(ItemStack.EMPTY);
                return ItemStack.EMPTY;
            }

            if (slotId < 9){
                Slot slot = this.inventorySlots.get(slotId);
                if (slot == null || !slot.canTakeStack(player)) {
                    return ItemStack.EMPTY;
                }
                ItemStack stack = slot.getStack();
                if (stack.isEmpty()){
                    return playerInvStack;
                }
                if (stack.getItem()!=playerInvStack.getItem()){
                    return playerInvStack;
                }
                if (!(stack.getItem() instanceof SplinterItem)){
                    return playerInvStack;
                }
                int level = ((SplinterItem)stack.getItem()).getLevel();

                Slot manaStoneSlot = this.inventorySlots.get(8+level);
                if (manaStoneSlot == null) {
                    return playerInvStack;
                }
                ItemStack manaStoneStack = manaStoneSlot.getStack();
                int consumeCount = SplinterItem.getCountByLevel(level);
                int manaStoneCount = manaStoneStack.getCount();

                if (consumeCount > manaStoneCount){
                    return playerInvStack;
                }

                if (playerInvStack.getCount()==playerInvStack.getMaxStackSize()){
                    return playerInvStack;
                }

                manaStoneStack.shrink(consumeCount);
                playerInvStack.setCount(playerInvStack.getCount()+1);
                return playerInvStack;
            }

            if (!(playerInvStack.getItem() instanceof ManaStoneItem)){
                return playerInvStack;
            }
            int level = ((ManaStoneItem)playerInvStack.getItem()).getLevel();
            if (slotId - 8 != level){
                return playerInvStack;
            }
        }

        if (slotId < 9){
            Slot slot = this.inventorySlots.get(slotId);
            if (slot == null || !slot.canTakeStack(player)) {
                return ItemStack.EMPTY;
            }
            ItemStack stack = slot.getStack();
            if (stack.isEmpty()){
                return ItemStack.EMPTY;
            }
            if (stack.getItem() instanceof SplinterItem){
                int level = ((SplinterItem)stack.getItem()).getLevel();

                Slot manaStoneSlot = this.inventorySlots.get(8+level);
                if (manaStoneSlot == null) {
                    return ItemStack.EMPTY;
                }
                ItemStack manaStoneStack = manaStoneSlot.getStack();
                if (manaStoneStack.isEmpty() || !(manaStoneStack.getItem() instanceof ManaStoneItem)){
                    return ItemStack.EMPTY;
                }
                int consumeCount = SplinterItem.getCountByLevel(level);
                int manaStoneCount = manaStoneStack.getCount();

                if (consumeCount > manaStoneCount){
                    return ItemStack.EMPTY;
                }

                manaStoneStack.shrink(consumeCount);
                player.inventory.setItemStack(stack.copy());
                return stack.copy();
            }else {
                slot.putStack(ItemStack.EMPTY);
                return ItemStack.EMPTY;
            }
        }

        return super.slotClick(slotId, dragType, clickTypeIn, player);
    }

    private ItemStack quickMove(int slotId, PlayerEntity player){
        Slot slot = this.inventorySlots.get(slotId);
        if (slot == null || !slot.canTakeStack(player)) {
            return ItemStack.EMPTY;
        }
        ItemStack stack = slot.getStack();
        if (stack.isEmpty()){
            return ItemStack.EMPTY;
        }

        if (slotId < 9){
            // TODO: 当有足够的 mana stone 时，一次性转换所有材料
            // 先画个饼，以后有时间再写
            return ItemStack.EMPTY;
        }

        if (slotId < 18){
            // 将物品移动到玩家背包里
            for (int i = 0; i < 4 * 9; i++) {
                int id = i + 18;
                Slot playerInvSlot = this.inventorySlots.get(id);
                if (playerInvSlot == null){
                    continue;
                }
                ItemStack playerInvStack = playerInvSlot.getStack();
                if (playerInvStack.isEmpty()){
                    playerInvSlot.putStack(stack.copy());
                    slot.putStack(ItemStack.EMPTY);
                    break;
                }
                if (playerInvStack.getItem()==stack.getItem()){
                    int stackSize = stack.getCount();
                    int maxSize = stack.getMaxStackSize();
                    int nowSize = playerInvStack.getCount();
                    if (nowSize==maxSize){
                        continue;
                    }
                    if (stackSize <= maxSize - nowSize){
                        slot.putStack(ItemStack.EMPTY);
                        playerInvStack.setCount(nowSize+stackSize);
                        break;
                    }
                    stack.setCount(stackSize-(maxSize-nowSize));
                    playerInvStack.setCount(maxSize);
                }
            }
            return ItemStack.EMPTY;
        }

        if (!(stack.getItem() instanceof ManaStoneItem)){
            return ItemStack.EMPTY;
        }

        int level = ((ManaStoneItem)stack.getItem()).getLevel();
        Slot manaStoneSlot = this.inventorySlots.get(8+level);
        if (manaStoneSlot == null || !manaStoneSlot.canTakeStack(player)){
            return ItemStack.EMPTY;
        }

        // 处理 mana stone
        ItemStack manaStoneStack = manaStoneSlot.getStack();
        if (manaStoneStack.isEmpty()){
            manaStoneSlot.putStack(stack.copy());
            slot.putStack(ItemStack.EMPTY);
        }
        else {
            int maxSize = manaStoneStack.getMaxStackSize();
            int nowSize = manaStoneStack.getCount();
            int stackSize = stack.getCount();
            if (stackSize > maxSize - nowSize){
                stack.setCount(stackSize-(maxSize-nowSize));
                manaStoneStack.setCount(maxSize);
            }
            else {
                slot.putStack(ItemStack.EMPTY);
                manaStoneStack.setCount(nowSize+stackSize);
            }
        }

        return ItemStack.EMPTY;
    }
}
